#include "mytest_def.h"
#include "reflect/test_reflect.h"

struct TypeInfo
{
    TypeInfo()
        : nmajor(1)
        , nminor(0)
    {
    }

    int nmajor;
    int nminor;
    _tstring classID;

    bool operator < (const TypeInfo& other) const
    {
        if (classID != other.classID) {
            return classID < other.classID;
        }

        if (nmajor != other.nmajor) {
            return nmajor < other.nmajor;
        }

        return nminor < other.nminor;
    }
};

struct ReflectInfo
{
    std::map<_tstring, std::set<TypeInfo>> classIDMapRTTi;
    std::map<TypeInfo, IReflectObject*> typeMap;
};

static inline ReflectInfo& GetRefMag()
{
    static ReflectInfo g_reflectInfo;
    return g_reflectInfo;
}

void RegisterReflectObject(IReflectObject* pObj, int versionMajor, int versionMinor)
{
    TypeInfo info;

    info.nmajor = versionMajor;
    info.nminor = versionMinor;
    info.classID = pObj->GetName();

    GetRefMag().classIDMapRTTi[pObj->GetName()].insert(info);
    GetRefMag().typeMap[info] = pObj;
}

void UnRegisterReflectObject(IReflectObject* pObj, int versionMajor, int versionMinor)
{
    TypeInfo info;

    info.nmajor = versionMajor;
    info.nminor = versionMinor;
    info.classID = pObj->GetName();

    GetRefMag().typeMap.erase(info);
    GetRefMag().classIDMapRTTi[info.classID].erase(info);
}

IReflectObject* GetReflectObject(const _tstring& pTypeName)
{
    TypeInfo info;

    auto itorRtti = GetRefMag().classIDMapRTTi.find(pTypeName);
    if (itorRtti != GetRefMag().classIDMapRTTi.end()) {
        if (!itorRtti->second.empty()) {
            info = *itorRtti->second.rbegin();
        }
    }

    auto ptem = GetRefMag().typeMap.find(info);
    if (ptem != GetRefMag().typeMap.end()) {
        return ptem->second;
    }

    return nullptr;
}
